﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Elderos.Utils.Logging;
using Elderos.Utils.SQL;

namespace Elderos.Articles
{
    public class ArticlesData : IArticlesData
    {
        public string ConnectionString { get; private set; }

        public ArticlesData(string connectionString)
        {
            Logger.Assert<ArgumentNullException>(() => connectionString != null, "Connection string cannot be null");
            ConnectionString = connectionString;
        }

        private static Article ReadArticle(IDataReader reader)
        {
            var article = new Article();
            article.Body = reader.GetField<string>("Body");
            article.Copyright = reader.GetField<string>("Copyright");
            article.Date = reader.GetField<DateTime>("Date");
            article.DateLine = reader.GetField<string>("Dateline");
            article.HasIdealHighlight = reader.GetField<bool>("HasIdealHighlight");
            article.Headline = reader.GetField<string>("Headline");

            string highlightString = reader.GetField<string>("Highlight");
            article.Highlight = highlightString == null ? null : XDocument.Parse(highlightString);
            article.ID = reader.GetField<int>("ID");

            string idealHighlightString = reader.GetField<string>("IdealHighlight");
            article.IdealHighlight = idealHighlightString == null ? null : XDocument.Parse(idealHighlightString);
            article.QueueNumber = reader.GetField<int>("QueueNumber");
            article.ReutersID = reader.GetField<int>("ReutersID");
            article.Title = reader.GetField<string>("Title");
            return article;
        }

        public async Task<Article> GetArticleAsync(int articleID)
        {
            return await new SqlQuery(ConnectionString).ExecuteSingleAsync(
@"select *
from Articles
where ID = @articleID",
                ReadArticle,
                new SqlParameter("articleID", articleID)
                );
        }

        public async Task<Article> GetArticleByQueueIDAsync(int queueID)
        {
            return await new SqlQuery(ConnectionString).ExecuteSingleAsync(
@"select *
from Articles
where QueueNumber = @queueID",
                ReadArticle,
                new SqlParameter("queueID", queueID)
                );
        }

        public List<int> GetIdealArticles()
        {
            return new SqlQuery(ConnectionString).ExecuteList(
@"select ID
from Articles
where HasIdealHighlight = 1",
                reader => reader.GetInt32(0)
                );
        }

        private static QueuedArticle ReadQueuedArticle(IDataReader reader)
        {
            var article = new QueuedArticle();
            article.ArticleID = reader.GetField<int>("ArticleID");
            article.QueueID = reader.GetField<int>("QueueID");
            article.Priority = reader.GetField<int>("Priority");
            article.Status = reader.GetField<int>("Status");
            return article;
        }

        public async Task<QueuedArticle> DequeueArticleAsync()
        {
            return await new SqlQuery(ConnectionString).ExecuteSingleAsync(
                new SqlCommand("DequeueArticle"){CommandType = CommandType.StoredProcedure},
                ReadQueuedArticle
                );
        }


        public async Task UpdateArticleAsync(Article article, SqlTransaction transaction = null)
        {
            await new SqlQuery(ConnectionString, transaction).ExecuteCmdAsync(
@"update Articles
set hasIdealHighlight = @hasIdealHighlight,
    highlight = @highlight,
    idealHighlight = @idealHighlight    
where id = @id",
                new SqlParameter("hasIdealHighlight", article.IdealHighlight != null),
                new SqlParameter("highlight", article.Highlight == null ? (object)DBNull.Value : article.Highlight.ToString()),
                new SqlParameter("id", article.ID),
                new SqlParameter("idealHighlight", article.IdealHighlight == null ? (object)DBNull.Value : article.IdealHighlight.ToString())
                );
        }


        public async Task UpdateQueuedArticleAsync(QueuedArticle article, SqlTransaction transaction = null)
        {
            await new SqlQuery(ConnectionString, transaction).ExecuteCmdAsync(
@"update highlightQueue
set Status = @status,
    priotiry = @priority
where queueID = @queueID",
                new SqlParameter("status", article.Status),
                new SqlParameter("priority", article.Priority),
                new SqlParameter("queueID", article.QueueID)
                );
        }

        public async Task<Article> GetUncheckedArticleAsync()
        {
            return await new SqlQuery(ConnectionString).ExecuteSingleAsync(
@"select top 1 *
from Articles
where IdealHighlight is null
order by QueueNumber",
                ReadArticle
                );
        }
    }
}
